package ru.urfc.portal.ui.client.descriptor;

import ru.urfc.portal.ui.client.renderers.BaseRenderer;
import ru.urfc.portal.ui.client.renderers.DoubleRenderer;
import ru.urfc.portal.ui.client.renderers.IntegerRenderer;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.ModelType;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Style;
import com.google.gwt.user.client.ui.HTML;

public abstract class GridField {
	protected GridDescriptor gridDescriptor;
	private String fieldName;
	private BaseRenderer renderer;

	public GridField init(String fieldName, GridDescriptor gridDescriptor, ModelType modelType) {
		this.gridDescriptor = gridDescriptor;
		this.fieldName = fieldName;
		return this;
	}
	
	public String getName() {
		return fieldName;
	}
	
	public ColumnConfig addColumn(final String title, int width) {
		ColumnConfig columnConfig = new ColumnConfig(null, title, width) {
			@Override
			public void setAlignment(final HorizontalAlignment alignment) {
				super.setAlignment(alignment);
				HTML widget = new HTML (Document.get().createSpanElement()) {
					@Override
					protected void onAttach() {
						super.onAttach();
						Style style = getElement().getParentElement().getStyle();
						if (alignment == HorizontalAlignment.RIGHT) {
							style.setProperty("paddingRight", "16px");
						}
						style.setProperty("textAlign", alignment.toString().toLowerCase());
					}
				};
				widget.setText(title);
				setWidget(widget, "");
			}			
		};
		return addColumn(columnConfig);
	}

	public ColumnConfig addColumn(ColumnConfig columnConfig) {
		columnConfig.setRenderer(renderer);
		gridDescriptor.addColumn(this, columnConfig);
		return columnConfig;
	}	

	public void updateViewFromModel(ModelData modelData) {
		renderer.renderElements(modelData);
	}
	
	/**
	 * Update value accord this field in the modelData from UI component if it exist   
	 */
	public void updateModelFromView(ModelData modelData) {
		if (getRenderer() != null) {
			getRenderer().updateModel(modelData);
		}
	}
	
	@SuppressWarnings("unchecked")
	public <T> T getValue(ModelData modelData) {
		return (T) _getValue(modelData);
	}

	public <T> void setValue(ModelData modelData, T value) {
		modelData.set(getName(), value);
	}
	
	protected abstract Object _getValue(ModelData modelData);

	@SuppressWarnings("unchecked")
	public <T extends BaseRenderer> T getRenderer() {
		return (T) renderer;
	}

	public abstract void accept(Visitor visitor);
	
	/**
	 * Just shortcuts
	 */
	public IntegerRenderer getIntRenderer() {
		return getRenderer();
	}

	public DoubleRenderer getDblRenderer() {
		return getRenderer();
	}

	void assign(BaseRenderer renderer) {
		this.renderer = renderer;
	}

	public GridField setEditable() {
		gridDescriptor.setEditable(this);
		return this;
	}
	
}
